/**
 * 
 */
package cn.edu.jlu.grid.vjm;

import java.util.Iterator;
import java.util.Vector;


/**
 * @author whb
 *
 */
public class VJMResourceSelectionStrategy implements IVJobDispatchStrategy {

	/* the maximum clusters that the parallel jobs can span */
	private static final int M = 6;

	/* (non-Javadoc)
	 * @see cn.edu.jlu.grid.vjm.IVJobDispatchStrategy#dispatch(cn.edu.jlu.grid.vjm.Cluster, int)
	 */
	public Vector<Cluster> dispatch(Vector<Cluster> clusters, int nVjobs) {
		if(clusters.size() == 0) return null;

		while(true) {
			for(int i = 0; i < nVjobs; i++) {
				int cmin, tmin;
				Cluster c;

				cmin = 0;
				c = clusters.get(0);
				tmin = c.averageWaitingTime - c.earilestJobWaitingTime +
				c.averageInterval * c.queueLength +
				c.averageInterval * c.vjobCount;

				for(int j = 1; j < clusters.size(); j++) {
					c = clusters.get(j);
					int t = c.averageWaitingTime - c.earilestJobWaitingTime +
					c.averageInterval * c.queueLength +
					c.averageInterval * c.vjobCount;

					if(t < tmin) {
						tmin = t;
						cmin = j;
					}
				}

				/* allocate vjob i to cluster indexed by cmin,
				 * at this time tmin is the expected waiting time 
				 * of vjob i, so update the corresponding parameters of 
				 * cluster cmin
				 */
				clusters.get(cmin).vjobCount++;
				if(tmin > clusters.get(cmin).maxExpectedWaitingTime)
					clusters.get(cmin).maxExpectedWaitingTime = tmin;
			}

			/* purge empty set */
			for(int i = 0; i < clusters.size(); i++) {
				if(clusters.get(i).vjobCount <= 0)
					clusters.remove(i);
			}

			/* check whether the size of the candidate set 
			 * exceeds the upper limit, if so, adjust the set
			 */
			if(clusters.size() > M) {
				int tmpcnt = clusters.get(0).vjobCount, tmpindex = 0;
				for(int i = 1; i < clusters.size(); i++) {
					if(clusters.get(i).vjobCount < tmpcnt) {
						tmpcnt = clusters.get(i).vjobCount;
						tmpindex = i;
					}
				}
				nVjobs = tmpcnt;
				clusters.remove(tmpindex);
			} else {
				break;
			}
		}

		return clusters;
	}
}
